package api

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v4"
	"go-chain-api/global"
	models "go-chain-api/internal/model"
	"go-chain-api/utils"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	"net/http"
	"time"
)

type Dapp struct{}

// Register 创建用户
func (d Dapp) Register(c *gin.Context) {
	var user models.User
	language := "zh-tw"
	err := c.ShouldBindJSON(&user)
	if err != nil {
		response := utils.GetResponse(err, utils.ParamBindError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	if user.Username == "" || user.Password == "" || user.Email == "" {
		response := utils.GetResponse(nil, utils.ParamNotNull, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	var emailCode models.EmailCode
	emailClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("email_code")
	findOptions := options.FindOne()
	findOptions.SetSort(bson.D{{"_id", -1}})

	err = emailClient.FindOne(context.TODO(), bson.M{"email": user.Email}, findOptions).Decode(&emailCode)
	if err != nil {
		response := utils.GetResponse(err, utils.EmailCodeError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}
	if emailCode.Code != user.EmailCode {
		response := utils.GetResponse(nil, utils.EmailCodeError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	//对比时间戳 保证验证码60s
	//如果生成的验证码+60s小于当前时间 那就说明过期了
	newTime := time.Unix(int64(emailCode.Timestamp), 0).Add(60 * time.Second).Unix()
	if newTime < time.Now().Unix() {
		response := utils.GetResponse(nil, utils.CodeExpired, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	//每个用户生成唯一支付地址
	//var registerConfig []models.RegisterConfig
	//registerConfigClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("register_config")
	//find, _ := registerConfigClient.Find(context.TODO(), bson.D{})
	//err = find.All(context.TODO(), &registerConfig)
	//if err != nil {
	//	response = global.Response{
	//		Code: http.StatusInternalServerError,
	//		Data: nil,
	//		Msg:  err.Error(),
	//	}
	//	c.JSON(http.StatusOK, response)
	//	return
	//}
	//
	//if len(registerConfig) == 0 {
	//	response = global.Response{
	//		Code: http.StatusInternalServerError,
	//		Data: nil,
	//		Msg:  "register config is not setting",
	//	}
	//	c.JSON(http.StatusOK, response)
	//	return
	//}

	// 将密码使用md5加密
	user.Status = 1
	user.Password = utils.MD5(user.Password)
	user.ApiKey = utils.MD5(user.Username + user.Password + "TianShengDapp20240410")
	user.Role = "0"
	_, err = user.CreateUser(user)
	if err != nil {
		response := utils.GetResponse(err, utils.InsertError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	//for _, config := range registerConfig {
	//	err = models.GenerateAddress(insertId, config.ChainId, config.ChainName)
	//	if err != nil {
	//		response = global.Response{
	//			Code: http.StatusInternalServerError,
	//			Data: nil,
	//			Msg:  err.Error(),
	//		}
	//		c.JSON(http.StatusOK, response)
	//		return
	//	}
	//}

	response := utils.GetResponse(nil, utils.Success, nil, language)

	c.JSON(http.StatusOK, response)
}

// Login 登录
func (d Dapp) Login(c *gin.Context) {
	var user models.User
	err := c.ShouldBindJSON(&user)
	language := "zh-tw"
	if err != nil {
		response := utils.GetResponse(err, utils.ParamBindError, nil, language)
		c.JSON(http.StatusBadRequest, response)
		return
	}

	// 将密码使用md5加密
	user.Password = utils.MD5(user.Password)
	result, err := user.GetUserByUsernameAndPassword(user.Username, user.Password)
	if err != nil {
		response := utils.GetResponse(err, utils.UserNameOrPasswordError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	if result.Status == 0 {
		response := utils.GetResponse(err, utils.UserStatusStop, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	claims := &models.Claims{
		Apikey: result.ApiKey,
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(models.JwtKey)
	if err != nil {
		response := utils.GetResponse(err, utils.GenerateTokenError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	//var generateAddress []models.GenerateAddressConfig
	//addressClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("generate_address_config")
	//addressList, _ := addressClient.Find(context.TODO(), bson.M{"userId": result.Id})
	//err = addressList.All(context.TODO(), &generateAddress)
	//if err != nil {
	//	response := utils.GetResponse(err, utils.MongodbFindDataError, nil)
	//	c.JSON(http.StatusOK, response)
	//	return
	//}

	//addressData := make(map[string]string)
	//for _, address := range generateAddress {
	//	addressData[address.ChainName] = address.Address
	//}

	data := make(map[string]interface{})
	data["token"] = tokenString
	data["userId"] = result.Id
	data["username"] = result.Username
	data["apiKey"] = result.ApiKey
	data["email"] = result.Email
	//data["address"] = addressData

	if result.MaturityTime == 0 {
		data["maturityTime"] = "0"
	} else {
		data["maturityTime"] = time.Unix(result.MaturityTime, 0).Format("2006-01-02 15:04:05")
	}
	response := utils.GetResponse(nil, utils.Success, data, language)
	c.JSON(http.StatusOK, response)
}

// GetCollectionList 获取监听的列表
func (d Dapp) GetCollectionList(c *gin.Context) {
	var watchAddressInfo models.WatchAddressInfo
	chainName := c.MustGet("chainName").(string)
	chainId := c.MustGet("chainId").(uint)
	pageIndex := c.MustGet("pageIndex").(uint)
	pageSize := c.MustGet("pageSize").(uint)
	verify := c.DefaultQuery("verify", "")
	language := c.MustGet("language").(string)
	count, list, err := watchAddressInfo.GetList(chainName, chainId, verify, pageIndex, pageSize)
	if err != nil {
		response := utils.GetResponse(err, utils.GetError, nil, language)
		c.JSON(http.StatusInternalServerError, response)
		return
	}

	data := global.Page{
		Total: count,
		List:  list,
	}

	response := utils.GetResponse(nil, utils.Success, data, language)

	c.JSON(http.StatusOK, response)
}

// UpdateCollectionRecord 修改归集记录
func (d Dapp) UpdateCollectionRecord(c *gin.Context) {
	language := c.MustGet("language").(string)
	var watchAddressInfo models.WatchAddressInfo
	err := c.ShouldBindJSON(&watchAddressInfo)
	if err != nil {
		response := utils.GetResponse(err, utils.ParamBindError, nil, language)
		c.JSON(http.StatusBadRequest, response)
		return
	}

	chainName := c.MustGet("chainName").(string)
	chainId := c.MustGet("chainId").(uint)

	from := watchAddressInfo.From
	to := watchAddressInfo.To
	token := watchAddressInfo.Token
	amount := watchAddressInfo.Amount
	txHash, err := watchAddressInfo.UpdateVerify(chainName, chainId, from, to, token, amount)
	if err != nil {
		response := utils.GetResponse(err, utils.UpdateError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	response := utils.GetResponse(nil, utils.Success, txHash, language)
	c.JSON(http.StatusOK, response)
}

// AddWatchAddress 添加监听地址
func (d Dapp) AddWatchAddress(c *gin.Context) {
	language := c.MustGet("language").(string)
	var watchAddressConfig models.WatchAddressConfig
	err := c.ShouldBindJSON(&watchAddressConfig)
	if err != nil {
		response := utils.GetResponse(err, utils.ParamBindError, nil, language)
		c.JSON(http.StatusBadRequest, response)
		return
	}

	// 根据apiKey 获取id
	userInfo := utils.GetUserInfoByApiKey(c, c.MustGet("apiKey").(string))
	watchAddressConfig.UserId = userInfo.Id

	err = watchAddressConfig.Insert()
	if err != nil {
		response := utils.GetResponse(err, utils.InsertError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}

	response := utils.GetResponse(nil, utils.Success, nil, language)
	c.JSON(http.StatusOK, response)
}

// GetWatchAddress 获取监听地址
func (d Dapp) GetWatchAddress(c *gin.Context) {
	apiKey := c.MustGet("apiKey").(string)
	pageIndex := c.MustGet("pageIndex").(uint)
	pageSize := c.MustGet("pageSize").(uint)

	language := c.MustGet("language").(string)
	// 根据apiKey 获取id
	userInfo := utils.GetUserInfoByApiKey(c, apiKey)

	var watchAddressConfig models.WatchAddressConfig
	count, list, err := watchAddressConfig.GetList(userInfo.Id, pageIndex, pageSize)
	if err != nil {
		response := utils.GetResponse(nil, utils.GetError, nil, language)
		c.JSON(http.StatusOK, response)
		return
	}
	data := global.Page{
		Total: count,
		List:  list,
	}
	response := utils.GetResponse(nil, utils.Success, data, language)

	c.JSON(http.StatusOK, response)
}

// DelWatchAddress 删除监听地址
func (d Dapp) DelWatchAddress(c *gin.Context) {
	var response global.Response
	id := c.Param("id")

	if id == "" {
		response = global.Response{
			Code: http.StatusBadRequest,
			Data: nil,
			Msg:  "参数错误",
		}
		c.JSON(http.StatusBadRequest, response)
		return
	}
	var watchAddressConfig models.WatchAddressConfig
	err := watchAddressConfig.DeleteById(id)
	if err != nil {
		response = global.Response{
			Code: http.StatusInternalServerError,
			Data: nil,
			Msg:  err.Error(),
		}
		c.JSON(http.StatusOK, response)
		return
	}

	response = global.Response{
		Code: http.StatusOK,
		Data: nil,
		Msg:  "success",
	}

	c.JSON(http.StatusOK, response)
}

// GenerateAddress 生成地址
